確保類別只會有一個物件實體存在,並提供單一存取窗口
單例模式(Singleton)只有一個類別,來控管物件的產生
並且定義一個方法作為介面,來讓外界經由此介面來存取唯一個體
但唯一可能出現問題的,會是Race Condition
多執行緒的競爭關係,會導致實體重複產生
class Singleton
@instance = new
private_class_method :new
def self.instance
@instance ||= Singleton.new
end
def some_business_logic
# do something
end
end
s1 = Singleton.instance
s2 = Singleton.instance
if s1.equal?(s2)
print 'Singleton works, both variables contain the same instance.'
else
print 'Singleton failed, variables contain different instances.'
end
Singleton works, both variables contain the same instance.
由於只要產生一個物件,所以不把new
作為公共介面使用
而是在instance
中判定是否有已經存在的物件存在@instance
內
若是沒有則new
出實體後存入,有的話直接取用@instance
即可
class Singleton
attr_reader :value
@instance_mutex = Mutex.new
private_class_method :new
def initialize(value)
@value = value
end
def self.instance(value)
return @instance if @instance
@instance_mutex.synchronize do
@instance ||= new(value)
end
@instance
end
def some_business_logic
# do something
end
end
def test_singleton(value)
singleton = Singleton.instance(value)
puts singleton.value
end
puts "If you see the same value, then singleton was reused (yay!)\n"\
"If you see different values, then 2 singletons were created (booo!!)\n\n"\
"RESULT:\n\n"
process1 = Thread.new { test_singleton('FOO') }
process2 = Thread.new { test_singleton('BAR') }
process1.join
process2.join
FOO
FOO
這裡使用的Mutex
就是讓我們自設計一個GIL
(Global Interpreter Lock)
當兩個執行序進行時,使用synchronize
確保一個執行序完成後,再執行下一個
而由於已經產生了物件,另一個執行緒就無法再次生成
(當然這種做法有一個風險,那就是造成Deadlock)
Singleton
類別是可以被繼承的,所以增加使用彈性文章不定期更新!
感謝大家 如有問題,再煩請大家指教!